package org.sqltomongo.orm;

import org.apache.commons.lang3.StringUtils;
import org.sqltomongo.cache.*;
import org.sqltomongo.cache.data.CacheManager;
import org.sqltomongo.cache.data.DefaultCacheManager;
import org.sqltomongo.cache.parser.ParserMemoryCache;
import org.sqltomongo.configure.SqlToMongoProperties;
import org.sqltomongo.plugin.InterceptorConfigurer;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.xml.sax.InputSource;

import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * @Classname ConfigurationBuilder
 * @Description
 * @Date 2022/8/24 21:00
 * @Created by wangchangjiu
 */
public class ConfigurationBuilder {

    public Configuration build(InterceptorConfigurer interceptorConfigurer, SqlToMongoProperties properties) throws Exception {

        // 构建配置核心对象
        Configuration configuration = new Configuration();

        // 读取配置
        if(StringUtils.isNotEmpty(properties.getPackageSearchPath())){
            ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
            Resource[] resources = resourcePatternResolver.getResources(properties.getPackageSearchPath());
            List<Element> list = new ArrayList<>(resources.length);
            for (Resource resource : resources) {
                // Dom4j 解析
                Document document = new SAXReader().read(new InputSource(new InputStreamReader(resource.getInputStream())));
                list.add(document.getRootElement());
            }
            // 解析 Mapper.xml文件 解析出结果保存  Map<String, XNode> 中
            configuration.setMapperElement(DomParser.parser(list));
        }

        // 添加拦截器
        interceptorConfigurer.addInterceptor(configuration);

        // 数据缓存
        SqlToMongoProperties.DataCacheProperties dataCacheProperties = properties.getDataCache();
        if(dataCacheProperties != null && dataCacheProperties.isCacheEnabled()){
            // 设置是否开启缓存
            Configuration.DataCache dataCache = new Configuration.DataCache();
            CacheManager cacheManager = new DefaultCacheManager();
            dataCache.setCacheManager(cacheManager);
            dataCache.setCacheEnabled(true);
            dataCache.setCache(cacheManager.createCache(dataCacheProperties.getCacheFullName()));
            configuration.setDataCache(dataCache);
        }
        configuration.setParserCache(loadParserCache(properties.getParserCache()));
        return configuration;
    }

    private Configuration.ParserCache loadParserCache(SqlToMongoProperties.ParserCacheProperties parserCacheProperties) {
        Configuration.ParserCache parserCache = new Configuration.ParserCache();
        String cacheFullName = parserCacheProperties == null? null : parserCacheProperties.getCacheFullName();
        if(StringUtils.isNotBlank(cacheFullName)){
            try {
                Class<?> aClass = Class.forName(cacheFullName);
                parserCache.setCache(Cache.class.cast(aClass.newInstance()));
            } catch (ClassNotFoundException | IllegalAccessException|InstantiationException e) {
                throw new RuntimeException("create cache " + cacheFullName + " fail ：" +  e.getMessage() );
            }
        } else {
            parserCache.setCache(new ParserMemoryCache());
        }
        return parserCache;
    }


}
